package com.gua.jbs.controller;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.DefaultFileItemFactory;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.log4j.Logger;
import org.json.JSONObject;

import com.gua.jbs.bean.ProductBean;
import com.gua.jbs.pojo.Jbspit;
import com.gua.jbs.service.IProductService;
import com.gua.jbs.serviceImpl.ProductService;
import com.gua.jbs.utility.ApplicationConstant;
import com.gua.jbs.utility.ApplicationException;
import com.gua.jbs.utility.ApplicationUtil;
import com.gua.jbs.utility.CollectionUtil;
import com.gua.jbs.utility.ExceptionMessage;
import com.gua.jbs.utility.StringUtil;

/**
 * Controller related to the addition of a new product in the system, edit and
 * delete functionality
 * 
 * @author Piyush
 * 
 */
public class ProductController extends BaseController {

	private static final Logger logger = Logger
			.getLogger(ProductController.class);
	private String filePath;
	private boolean isMultipart;
	private File file;
	private String fullFilePath = null;
	private IProductService productservice = null;

	public ProductController() {
		productservice = new ProductService();
	}

	public void init() {
		// Get the file location where it would be stored.
		filePath = getServletContext().getInitParameter("file-upload");
	}

	public void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// Check that we have a file upload request
		isMultipart = FileUpload.isMultipartContent(request);

		String action = null;
		String productName = null;
		String productType = null;
		String productSubType = null;
		String productColor = null;
		String productPolish = null;
		String productQuantity = null;
		String productSize = null;
		String productRate = null;
		String productWeight = null;
		String prodNumBarcode = null;
		String productImage = null;
		String productDescription = null;
		String productAbout = null;
		String approval = null;
		String designCode = null;
		String hrCode = null;
		String costPrice = null;
		String prodId = null;

		action = request.getParameter(ApplicationConstant.ACTION);
		String message = request.getParameter(ApplicationConstant.MESSAGE);

		if (isMultipart) {
			DefaultFileItemFactory factory = new DefaultFileItemFactory();
			// maximum size that will be stored in memory
			// factory.setSizeThreshold(maxMemSize);

			// Location to save data that is larger than maxMemSize.
			// factory.setRepository(new File("N:\\temp"));

			// Create a new file upload handler
			FileUpload upload = new FileUpload(factory);

			// maximum file size to be uploaded.
			// upload.setSizeMax(maxFileSize);

			try {
				// Parse the request to get file items.
				List fileItems = upload.parseRequest(request);

				// Process the uploaded file items
				Iterator i = fileItems.iterator();
				while (i.hasNext()) {
					FileItem fi = (FileItem) i.next();
					if (fi != null) {

						// Get the uploaded file parameters
						String name = fi.getFieldName();
						String fileName = fi.getName();
						String value = fi.getString();

						// Get the action parameter to understand the type of
						// request
						if (StringUtil.isNullOrEmpty(name)) {
							if (name.equals(ApplicationConstant.ACTION))
								action = value;
							else if (name
									.equals(ApplicationConstant.productName))
								productName = value;
							else if (name
									.equals(ApplicationConstant.productType))
								productType = value;
							else if (name
									.equals(ApplicationConstant.productSubType))
								productSubType = value;
							else if (name
									.equals(ApplicationConstant.productColor))
								productColor = value;
							else if (name
									.equals(ApplicationConstant.productPolish))
								productPolish = value;
							else if (name
									.equals(ApplicationConstant.productQuantity))
								productQuantity = value;
							else if (name
									.equals(ApplicationConstant.productSize))
								productSize = value;
							else if (name
									.equals(ApplicationConstant.productRate))
								productRate = value;
							/*
							 * else if (name
							 * .equals(ApplicationConstant.productWeight))
							 * productWeight = value;
							 */
							else if (name
									.equals(ApplicationConstant.PRODUCT_COST_PRICE))
								costPrice = value;
							else if (name
									.equals(ApplicationConstant.productImage)) {
								if (StringUtil.isNullOrEmpty(value)) {
									// Write the file
									if (fileName.lastIndexOf("\\") >= 0) {
										fullFilePath = filePath
												+ fileName.substring(fileName
														.lastIndexOf("\\"));
										file = new File(fullFilePath);
									} else {
										fullFilePath = filePath
												+ fileName.substring(fileName
														.lastIndexOf("\\") + 1);
										file = new File(fullFilePath);
									}
									fi.write(file);
									productImage = value;
								}
							} else if (name
									.equals(ApplicationConstant.productAbout))
								productAbout = value;
							else if (name
									.equals(ApplicationConstant.productApprove))
								approval = value;
							else if (name
									.equals(ApplicationConstant.DESIGN_CODE))
								designCode = value;

							else if (name.equals(ApplicationConstant.HR_CODE))
								hrCode = value;

							else if (name.equals(ApplicationConstant.NUM_CODE))
								prodNumBarcode = value;
							else if (name.equals(ApplicationConstant.PROD_ID))
								prodId = value;

						}
					}
				}
			} catch (Exception ex) {
				System.out.println(ex);
			}

		}

		if (StringUtil.isNullOrEmpty(action)
				&& action.equals(ApplicationConstant.ADD_PRODUCT)) {
			String counter = "";
			try {
				// Set values them in the product bean
				ProductBean productBean = new ProductBean();
				productBean.setName(productName);
				productBean.setType(productType);
				productBean.setDesignCode(designCode);
				productBean.setColor(productColor);
				// productBean.setWeight(productWeight);
				productBean.setImage(fullFilePath);

				// Get the auto generated bar code by calling service
				counter = productservice.getGeneratorCounter();
				productBean.setBarCode(ApplicationUtil.getBarCode(counter));
				logger.debug("Bar CODE :" + ApplicationUtil.getBarCode(counter));

				// productBean.setBarCode(prodNumBarcode);
				productBean.setPrice(productRate);
				productBean.setCostPrice(costPrice);
				productBean.setQuantity(productQuantity);
				productBean.setPolish(productPolish);
				productBean.setDesc(productDescription);

				// Prepare the contentcode List for HR code
				List<String> codeContentList = new ArrayList<String>();
				codeContentList.add(productType);
				codeContentList.add(productSubType);
				codeContentList.add(productColor);
				codeContentList.add(productPolish);
				codeContentList.add(productSize);
				codeContentList.add(designCode);

				// Call the private method to get HR code
				hrCode = prepareHrCode(codeContentList, request);

				productBean.setHrCode(hrCode);
				productBean.setSize(productSize);
				productBean.setDesc(productAbout);
				productBean.setSubtype(productSubType);
				productBean.setIsApproved(approval);

				// Call the service layer to add the product in database
				prodId = productservice.addProduct(productBean);
			} catch (Exception e) {
				logger.error("Exception in Product Controller while Adding Product--->"+e);
			}
				if (StringUtil.isNullOrEmpty(prodId)) {

					// Update the Bar code generator by 1
					try {
						boolean isUpdated = productservice
								.updateGeneratorCounter(counter);
						if (isUpdated == false)
							logger.error(ExceptionMessage.BAR_CODE_GENERATOR_UPDATE_FAILED);
					} catch (ApplicationException ae) {
						logger.error(ExceptionMessage.BAR_CODE_GENERATOR_UPDATE_FAILED+"-->"+ae);
					}
					request.setAttribute("message",
							ApplicationConstant.PRODUCT_SAVE_SUCCESSFUL);
					response.sendRedirect("actionOnProduct?ACTION=EP&&prodId="
							+ prodId+"&&message="+ApplicationConstant.PRODUCT_SAVE_SUCCESSFUL);
				} else {
					request.setAttribute("message",
							ApplicationConstant.PRODUCT_SAVE_UNSUCCESSFUL);
					message=ApplicationConstant.PRODUCT_SAVE_UNSUCCESSFUL;
					rd = request
							.getRequestDispatcher("/productEntry?message="+message);
					rd.forward(request, response);
				}
			
			// productservice.updateGeneratorCounter();

		} else if (StringUtil.isNullOrEmpty(action)
				&& action.equals(ApplicationConstant.EDIT_PRODUCT)) {

			// prodId = request.getParameter("prodId");

			ProductBean productBean = new ProductBean();
			productBean.setId(prodId);
			productBean.setName(productName);
			productBean.setType(productType);
			productBean.setColor(productColor);
			productBean.setImage(productImage);
			productBean.setPrice(productRate);
			productBean.setCostPrice(costPrice);
			productBean.setQuantity(productQuantity);
			productBean.setPolish(productPolish);
			productBean.setSize(productSize);
			productBean.setDesc(productAbout);
			productBean.setSubtype(productSubType);
			productBean.setIsApproved(approval);
			productBean.setDesignCode(designCode);
			productBean.setBarCode(prodNumBarcode);
			
			// Prepare the contentcode List for HR code
			List<String> codeContentList = new ArrayList<String>();
			codeContentList.add(productType);
			codeContentList.add(productSubType);
			codeContentList.add(productColor);
			codeContentList.add(productPolish);
			codeContentList.add(productSize);
			codeContentList.add(designCode);

			// Call the private method to get HR code
			hrCode = prepareHrCode(codeContentList, request);
			productBean.setHrCode(hrCode);
			try {
				boolean isUpdate = productservice.updateProduct(productBean,
						prodId);
				message = null;
				if (isUpdate)
					message = ApplicationConstant.PRODUCT_UPDATE_SUCCESSFUL;
				else
					message = ApplicationConstant.PRODUCT_UPDATE_UNSUCCESSFUL;
				request.setAttribute("message", message);
				response.sendRedirect("actionOnProduct?ACTION=EP&&prodId="
						+ prodId);
			} catch (Exception e) {

			}

		} else if (StringUtil.isNullOrEmpty(action)
				&& action.equals(ApplicationConstant.DELETE_PRODUCT)) {

			// prodId = request.getParameter("prodId");
			try {
				boolean isDelete = productservice.deleteProduct(prodId);
				if (isDelete) {
					rd = request
							.getRequestDispatcher("/pages/jsp/allproductInfo.jsp");
					rd.forward(request, response);
				}
			} catch (Exception e) {

			}
		} else if (StringUtil.isNullOrEmpty(action)
				&& action.equals(ApplicationConstant.FILTER_ON_DATE)) {
			String fromDate = request
					.getParameter(ApplicationConstant.FROM_DATE);
			String toDate = request.getParameter(ApplicationConstant.TO_DATE);

			if (StringUtil.isNullOrEmpty(fromDate)
					&& StringUtil.isNullOrEmpty(toDate)) {
				List<Jbspit> list_products = new ArrayList<Jbspit>();
				try {
					list_products = productservice.getProductsByDateFilter(
							fromDate, toDate);
				} catch (ApplicationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				logger.info("list_products==" + list_products.size());
				boolean isListEmpty = CollectionUtil.isEmptyList(list_products);

				if (isListEmpty == false) {
					request.setAttribute("productList", list_products);
				}
				rd = request
						.getRequestDispatcher("/pages/jsp/allProductInfo.jsp");
				rd.forward(request, response);
			}

		} else if (StringUtil.isNullOrEmpty(action)
				&& action.equals(ApplicationConstant.SCAN_PRODUCT)) {
			String scanProdCode = request.getParameter("scanProdCode");
			JSONObject obj = new JSONObject();
			try {
				if (StringUtil.isNullOrEmpty(action)
						&& action.equals(ApplicationConstant.SCAN_PRODUCT)) {

					ProductBean productBean = productservice
							.getProductByCode(scanProdCode);
					obj.put("name", productBean.getName());
					obj.put("desc", productBean.getDesc());
					obj.put("price", productBean.getPrice());
					logger.info("obj===" + obj);
				}
				PrintWriter writer = response.getWriter();
				writer.print(obj.toString());

			} catch (ApplicationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		else {
			Map<Integer, Map<String, String>> map_prodType = new LinkedHashMap<Integer, Map<String, String>>();
			Map<Integer, Map<String, String>> map_prodSubType = new LinkedHashMap<Integer, Map<String, String>>();

			Map<Integer, Map<String, String>> map_prodColor = new LinkedHashMap<Integer, Map<String, String>>();
			Map<Integer, Map<String, String>> map_prodPolish = new LinkedHashMap<Integer, Map<String, String>>();
			Map<Integer, Map<String, String>> map_prodSize = new LinkedHashMap<Integer, Map<String, String>>();

			try {
				map_prodType = productservice.getProductsType();
				map_prodSubType = productservice.getProductsSubType();
				map_prodColor = productservice.getProductsColor();
				map_prodPolish = productservice.getProductsPolish();
				map_prodSize = productservice.getProductsSize();
				HttpSession session = request.getSession(true);

				request.setAttribute("productTypes", map_prodType);
				session.setAttribute("productTypes", map_prodType);

				request.setAttribute("productSubTypes", map_prodSubType);
				session.setAttribute("productSubTypes", map_prodSubType);

				request.setAttribute("productColor", map_prodColor);
				session.setAttribute("productColor", map_prodColor);

				request.setAttribute("productPolish", map_prodPolish);
				session.setAttribute("productPolish", map_prodPolish);

				request.setAttribute("productSize", map_prodSize);
				session.setAttribute("productSize", map_prodSize);

			} catch (ApplicationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			request.setAttribute("message", message);
			rd = request.getRequestDispatcher("/pages/jsp/productEntry.jsp");
			rd.forward(request, response);
		}

	}
	
	private void getProductCatagory(HttpServletRequest request){
		Map<Integer, Map<String, String>> map_prodType = new LinkedHashMap<Integer, Map<String, String>>();
		Map<Integer, Map<String, String>> map_prodSubType = new LinkedHashMap<Integer, Map<String, String>>();

		Map<Integer, Map<String, String>> map_prodColor = new LinkedHashMap<Integer, Map<String, String>>();
		Map<Integer, Map<String, String>> map_prodPolish = new LinkedHashMap<Integer, Map<String, String>>();
		Map<Integer, Map<String, String>> map_prodSize = new LinkedHashMap<Integer, Map<String, String>>();

		try {
			map_prodType = productservice.getProductsType();
			map_prodSubType = productservice.getProductsSubType();
			map_prodColor = productservice.getProductsColor();
			map_prodPolish = productservice.getProductsPolish();
			map_prodSize = productservice.getProductsSize();
			HttpSession session = request.getSession(true);

			session.setAttribute("productTypes", map_prodType);

			
			session.setAttribute("productSubTypes", map_prodSubType);

			
			session.setAttribute("productColor", map_prodColor);

			session.setAttribute("productPolish", map_prodPolish);

			session.setAttribute("productSize", map_prodSize);

		} catch (ApplicationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Private method to prepare HR code
	 * 
	 * @param contentList
	 * @param request
	 * @return
	 */
	private String prepareHrCode(List<String> contentList,
			HttpServletRequest request) {
		String hrCode = "";
		String finalHrCode = "";
		HttpSession session = request.getSession(true);
		Map<Integer, Map<String, String>> codeMap = null;

		// Prepare maps placed in session name list
		String[] codeMapName = { "productTypes", "productSubTypes",
				"productColor", "productPolish", "productSize" };
		try {
			if (!CollectionUtil.isEmptyList(contentList)) {
				for (int count = 0; count < contentList.size(); count++) {
					// Get the code from the session maps and prepare HR code
					if (count != contentList.size() - 1) {
						codeMap = (Map<Integer, Map<String, String>>) session
								.getAttribute(codeMapName[count]);
						/**
						 * TO DO
						 */
						if(codeMap==null){
							getProductCatagory(request);
							codeMap = (Map<Integer, Map<String, String>>) session
									.getAttribute(codeMapName[count]);
						}
						if (codeMap != null && codeMap.isEmpty() != true) {
							String codecontent = contentList.get(count);
							if (StringUtil.isNullOrEmpty(codecontent)) {
								Map<String, String> innerCodeMap = (Map<String, String>) codeMap
										.get(Integer.parseInt(codecontent));
								if (codeMap != null
										&& codeMap.isEmpty() != true) {
									for (Map.Entry<String, String> entry : innerCodeMap
											.entrySet()) {
										String code = (String) entry.getValue();
										hrCode = hrCode + code;
									}
								}
							}
						}
					}
					// Add last value passed i.e. design code into HR code
					else
						hrCode = hrCode + contentList.get(count);
				}
			}
			logger.debug("HR CODE :" + hrCode);
			finalHrCode = hrCode.toUpperCase();
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		return finalHrCode;
	}
}
